#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#if 1
#define ILLEGAL_ID	((char)0xff)
#define LEGAL_ZERO	((char)0xfe)
struct st_country
{
#define ST_COUNTRY_TYPE_COUNTRY	1
#define ST_COUNTRY_TYPE_USERID	2
	char type;	// 1:country;  0:userid(Dec)
#define SIZE_COUNTRY_ST_DATA	64
	char data[SIZE_COUNTRY_ST_DATA];
	struct st_country *next;
};
#endif

struct st_country country_h = {0};		// head
struct st_country *country_hp = &country_h;	// pointer to head

/****
 * ARG1 (str) : a line
 */
int country_data_insert(struct st_country *head, const char *str)
{
	struct st_country *prev = head;

	while( head->next )
	{
		head = head->next;

		///
		///

		prev = head;
	}

	/* Create */
	struct st_country *new = (struct st_country *)malloc(sizeof(struct st_country));

	/* Init */
	new->type = -1;
	new->next = NULL;

	/* Process data(string) */
	if( str[0] > 'a' && str[0] < 'z'  || str[0] > 'A' && str[0] < 'Z' )	// This line is country name;
	{
		memset(new->data, 0, SIZE_COUNTRY_ST_DATA);
		new->type = ST_COUNTRY_TYPE_COUNTRY;
		strncpy(new->data, str, strlen(str)<SIZE_COUNTRY_ST_DATA?strlen(str):SIZE_COUNTRY_ST_DATA);
		printf("[%s,%d] (%s)\n", __func__,__LINE__, new->data);
		new->data[SIZE_COUNTRY_ST_DATA-1] = 0;
	}
	else	// This line contents userids
	{
		memset(new->data, ILLEGAL_ID, SIZE_COUNTRY_ST_DATA);
		new->type = ST_COUNTRY_TYPE_USERID;

		int index = 0;
		char *token = NULL;
		char *tmp = (char *)malloc(SIZE_COUNTRY_ST_DATA);
		memset(tmp, 0, SIZE_COUNTRY_ST_DATA);
		memcpy(tmp, str, SIZE_COUNTRY_ST_DATA);
		tmp[SIZE_COUNTRY_ST_DATA-1] = 0;
		while(NULL != (token = strsep(&tmp, " ")))
		{
			if( index >= SIZE_COUNTRY_ST_DATA )
				index = 0;

			new->data[index] = atoi(token)==0?LEGAL_ZERO:atoi(token);
			printf("[%s,%d] (%s)(%d)\n", __func__,__LINE__, token, new->data[index]);

			index++;
		}

	}

	/* Insert */
	head->next = new;

	return 0;
}

/*
 * ARG0 (head)		: pointer point to head;
 * ARG1 (ac)		: Arg Country name;
 * ARG2 (aid)		: Arg user ID;
 * ARG3 (outbuff)	: Output buff;
 */
int country_data_dump(struct st_country *head, const char *ac, char aid, char *outbuff)
{
	int itmp = 0; // tmp index

	int iusers = 0;
	char ausers[SIZE_COUNTRY_ST_DATA];// all users of the country
	memset(ausers, ILLEGAL_ID, SIZE_COUNTRY_ST_DATA);

	struct st_country *prev = head;
	if( 0==aid )
	aid = LEGAL_ZERO;
	printf("[%s,%d] Dump country=(%s), id=(%d) \n",__func__,__LINE__,ac?ac:"ALL", aid);

	memset(outbuff, ILLEGAL_ID, SIZE_COUNTRY_ST_DATA);

	char flag_country_is = 0;
	while( head->next )
	{
		head = head->next;

		///
		if( ST_COUNTRY_TYPE_COUNTRY == head->type )
		{
			if ( NULL != ac )
			{
				if( 0 == strncmp(head->data, ac, SIZE_COUNTRY_ST_DATA-1) )
				{
					printf("Country : (%s)\n", head->data);
					flag_country_is = 1;
				}
				else
				{
					flag_country_is = 0;
					continue;
				}
			}
			else
			{
				printf("Country : (%s)\n", head->data);
				flag_country_is = 1;
			}
		}
		else if( ST_COUNTRY_TYPE_USERID == head->type )
		{
			if( (0 == flag_country_is)){			// Country not match
				continue;
			}

			if( (ILLEGAL_ID != aid && aid != head->data[0]) ){	// Spec id && id not match
				if(iusers<SIZE_COUNTRY_ST_DATA){
					ausers[iusers] = head->data[0];	// All id of the Country except self
					printf("&Add [%d] : (%d,0x%x)\n",iusers, ausers[iusers], ausers[iusers]);
					iusers++;
				}
				continue;
			}

			for(itmp=0; itmp<SIZE_COUNTRY_ST_DATA; itmp++){
				if( outbuff ){
					outbuff[itmp] = head->data[itmp];	// Copy to outbuff
				}

				if( ILLEGAL_ID == head->data[itmp] ){ // Null data after, break;
					break;
				}

				if( 0 == itmp ){ // first id of the line
					printf("_[%d] ", head->data[itmp]);
				}
				else{
					printf("_(%d) ", head->data[itmp]);
				}
			}
			printf("\n");

		}
		else
		{
			printf("%s,%d ERROR !!\n",__func__,__LINE__);
		}
		///

		prev = head;
	}



#if 1
	//printf("\n##############outbuff\n");
	//for(itmp=0;itmp<SIZE_COUNTRY_ST_DATA;itmp++){ printf(" 0x%02x", (char)outbuff[itmp]); }
	//printf("\n##############others\n");
	//for(itmp=0;itmp<SIZE_COUNTRY_ST_DATA;itmp++){ printf(" 0x%02x", (char)ausers[itmp]); }
	//printf("\n##############\n");
	/* check if already recommended */
	int index = 0;
	for(index=0; index<SIZE_COUNTRY_ST_DATA; index++){
		for(itmp=0; itmp<SIZE_COUNTRY_ST_DATA; itmp++){
			if( ausers[itmp] == outbuff[index] ){
				//printf("Del [%d] : %d(0x%x)\n",itmp, ausers[itmp],ausers[itmp]);
				ausers[itmp] = ILLEGAL_ID;
			}
		}
	}
	/* Recommend process */
	if( ILLEGAL_ID == outbuff[0] )	// User not found
	{
		printf(">>>> user (%d|%d) not found\n", aid,ILLEGAL_ID);
		printf(">>>> user (%d) not found\n", aid);
	}
	else
	{
		/* check if already recommended */
		char flag_all_recommend = 1;
		for(itmp=0; itmp<SIZE_COUNTRY_ST_DATA; itmp++){
			printf("%d?=%d\n",ILLEGAL_ID, ausers[itmp]);
			if( ILLEGAL_ID != ausers[itmp] ){	// not all
				flag_all_recommend = 0;
				break;
			}
		}

		// If connected to all other
		if( flag_all_recommend )
		{
			printf(">>>> (%d) is already connected to all other users, no new recommendation\n", aid);
		}
		else
		{
			printf(">>>> recommend new friend %d to user %d (common neighbors = %d)\n"
					,outbuff[1]
					,aid==LEGAL_ZERO?0:aid
					,outbuff[1]-aid
			      );
		}
	}
#endif

	return 0;
}

int country_get_recommend()
{
}

#define IS_DEMO	1
int country_data_init(const char *afile, struct st_country *ahead)
{
#if IS_DEMO
	country_data_insert(ahead, "Canada");
	country_data_insert(ahead, "55 66 77 88");
	country_data_insert(ahead, "6 99 33 44");
#else
	FILE *fp = fopen(afile, "r");
	char buff[SIZE_COUNTRY_ST_DATA];
	memset(buff, 0, SIZE_COUNTRY_ST_DATA);
	while( NULL != fgets(buff, SIZE_COUNTRY_ST_DATA, fp) )
	{
		/* Del CR LF */
		char *tmp = NULL;
		tmp = strchr(buff, '\n');
		if(tmp)
			*tmp = 0;
		tmp = strchr(buff, '\r');
		if(tmp)
			*tmp = 0;

		/* Debug print */
		buff[SIZE_COUNTRY_ST_DATA-1] = 0;
		printf("FGETS : (%s)\n", buff);

		/* Insert data */
		country_data_insert(ahead, buff);

		/* Clean buff */
		memset(buff, 0, SIZE_COUNTRY_ST_DATA);
	}
	fclose(fp);
#endif


	return 0;
}

#if 1
int main(int argc, char **argv)
{
	country_data_init(argv[1], country_hp);

	country_data_dump(country_hp, NULL, 0, NULL);
	country_data_dump(country_hp, "Canada", 0, NULL);
	country_data_dump(country_hp, "xxxxxx", 0, NULL);
	country_data_dump(country_hp, "Canada", 6, NULL);
	country_data_dump(country_hp, "Canada", 78, NULL);

	return 0;
}
#endif
